package main

import (
	"fmt"
	"github.com/gorilla/sessions"
	"github.com/labstack/echo-contrib/session"
	"github.com/labstack/echo/v4"
	"io"
	"net/http"
	"os"
)

type UserInfoRequest struct {
	Name string `json:"name" query:"name" form:"name" xml:"name"`
	Age  int    `json:"age" query:"age" form:"age" xml:age1`
}

type LoginRequest struct {
	UserName string `json:"userName" query:"userName" form:"userName" xml:"userName"`
	Password string `json:"password" query:"password" form:"password" xml:password`
}

func main() {
	//实例化一个echo对象
	e := echo.New()
	e.GET("/test1", func(c echo.Context) error {
		return c.String(http.StatusOK, "你好")
	})

	//各种路由请求
	//get /get1/:id,/get1/1 那么id=1
	e.GET("/get1/:id", func(c echo.Context) error {
		id := c.Param("id")
		return c.String(http.StatusOK, id)
	})
	// get2?name=wq&age=30
	e.GET("/get2", func(c echo.Context) error {
		name := c.QueryParam("name")
		age := c.QueryParam("age")
		return c.String(http.StatusOK, name+age)
	})
	// 带星号的匹配
	// 可用匹配 /foods/1， /foods/200, /foods/1/20, /foods/apple/1
	// 注意如果匹配到了多个路由策略，那么优先级是 静态>参数>*匹配
	e.GET("/get3/*", func(c echo.Context) error {
		param := c.QueryParam("name")
		return c.String(http.StatusOK, param)
	})
	//对象接收 /get4?name=wq&age=30
	e.GET("/get4", func(c echo.Context) error {
		u := new(UserInfoRequest)
		err := c.Bind(u)
		if err != nil {
			fmt.Printf(err.Error())
		}
		return c.JSON(http.StatusOK, u)
	})
	//对象接收 /get4?name=wq&age=30
	e.GET("/get5", func(c echo.Context) error {
		u := new(UserInfoRequest)
		err := c.Bind(u)
		if err != nil {
			fmt.Printf(err.Error())
		}
		return c.XML(http.StatusOK, u)
	})
	//post 构造体接收参数
	e.POST("/post1", func(c echo.Context) error {
		u := new(UserInfoRequest)
		err := c.Bind(u)
		if err != nil {
			fmt.Printf(err.Error())

		}
		return c.JSON(http.StatusOK, u)

	})
	// post2 form表单接收参数
	e.POST("/post2", func(c echo.Context) error {
		value := c.FormValue("name")
		return c.JSON(http.StatusOK, value)

	})

	//put 类似
	//delete 类似
	//文件上传

	e.POST("/upload-file", func(c echo.Context) error {
		file, err := c.FormFile("file")
		if err != nil {
			fmt.Printf(err.Error())

		}
		//打开上传文件
		open, err := file.Open()
		if err != nil {
			fmt.Printf(err.Error())

		}
		defer open.Close()
		// 需要保存的文件
		create, err := os.Create("static/" + file.Filename)
		if err != nil {
			fmt.Printf(err.Error())

		}
		defer create.Close()
		_, err = io.Copy(create, open)
		if err != nil {
			fmt.Printf("文件写入磁盘错误" + err.Error())
		}
		return c.String(200, "上传成功")
	})
	//文件下载
	e.GET("/file1", func(c echo.Context) error {
		//通过File函数，直接返回本地文件，参数为本地文件地址 文本
		return c.File("static/我是测试文件.txt")
	})
	e.GET("/file2", func(c echo.Context) error {
		//通过File函数，直接返回本地文件，参数为本地文件地址 图片
		return c.File("static/猫爷.pdf")
	})
	e.GET("/file3", func(c echo.Context) error {
		//通过File函数，直接返回本地文件，参数为本地文件地址 图片
		return c.File("static/1234qwer.mp4")
	})
	e.GET("/file4", func(c echo.Context) error {
		// 指定文件名下载
		return c.Attachment("static/1234qwer.mp4", "1.mp4")
	})
	e.GET("/file5", func(c echo.Context) error {
		// 通过Stream函数，以stream流的方式返回文件
		open, err := os.Open("static/猫爷.pdf")
		if err != nil {
			fmt.Printf(err.Error())

		}
		return c.Stream(http.StatusOK, "application/pdf", open)
	})

	// 设置header
	e.GET("/header1", func(c echo.Context) error {
		c.Response().Header().Set("token", "sdsa")
		return c.String(200, "asdasd")

	})

	// 处理cookie
	//设置cookie
	e.GET("/set-coolie", func(c echo.Context) error {
		cookie := new(http.Cookie)
		cookie.Name = "wq-domian"
		cookie.Value = "wq-domian.com"
		cookie.Path = "/"
		cookie.MaxAge = 3600
		c.SetCookie(cookie)
		return c.String(200, "设置cookie成功")

	})
	//获取cookie
	e.GET("/get-cookie", func(c echo.Context) error {
		cookie, err := c.Cookie("wq-domian")
		if err != nil {
			fmt.Printf(err.Error())

		}
		return c.JSON(200, cookie)
	})
	//删除cookie
	e.GET("/del-cookie", func(c echo.Context) error {
		cookie, err := c.Cookie("wq-domian")
		if err != nil {
			fmt.Printf(err.Error())

		}
		cookie.MaxAge = -1
		c.SetCookie(cookie)
		return c.String(200, "删除ok")
	})
	// session 中间件实现
	sessionPath := "./session_data"
	sessionKey := "dasdas343"
	e.Use(session.Middleware(sessions.NewFilesystemStore(sessionPath, []byte(sessionKey))))

	// 设置session
	e.POST("/login", func(c echo.Context) error {
		loginInfo := new(LoginRequest)
		err := c.Bind(loginInfo)
		if err != nil {
			fmt.Printf(err.Error())

		}

		if loginInfo.UserName == "wq" && loginInfo.Password == "wq" {
			sess, _ := session.Get("userInfo", c)
			sess.Options = &sessions.Options{
				Path:   "/",
				MaxAge: 86400 * 7,
			}
			sess.Values["userName"] = "wq"
			sess.Values["isLogin"] = true
			sess.Save(c.Request(), c.Response())
			fmt.Println(sess.Values["userName"])
			return c.String(200, "登录成功")
		} else {
			return c.String(200, "登录失败")
		}
	})

	// 获取session TODO 并没有成功，猜测可能是文件存储的问题？
	e.GET("/home", func(c echo.Context) error {
		sess, err := session.Get("user_session", c)
		if err != nil {
			return c.String(200, "没有登录")
		}
		fmt.Println(sess.Values)
		userName := sess.Values["userName"]
		fmt.Println(userName)
		//isLogin := sess.Values["isLogin"]
		return c.String(200, "ok")
	})

	e.Start(":8080")
}
